#include <sys/kernel.h>
#include <sys/types.h>
#include "console.h"
#include <debug.h>

/*
 * All Kernel's IO methods, such as kprint ..
 */

static Console* console = new Console(); 

/* Format a string and print it on the screen, just like the libc
function printf. */
void Kernel::kprintf (const char *format, ...) {
	char **arg = (char **) &format;
	int c;
	char buf[20];
	arg++;

	while ((c = *format++) != 0) {
	        if (c == '%') { // mask
		        char *p;
		        c = *format++;
		        switch (c) {
		        	// do the same for all this cases
		        	case 'd':
		            case 'u':
		            case 'x':
	                	convert(buf, c, *((int *) arg++));
		                p = buf;
		                break;

	                case 's':
	                	p = *arg++;
	                	if (! p)
	                	p = "(null)";
		                break;

	                default:
		                console->putchar(*((int *) arg++));
		                break;
		        }
		        kprintf(p);
	        } else { 
	        	console->putchar(c);
	        } // end if-else
	} // end while
}



/* Convert the integer n, in a given base, to a string and puts the result in the 
 * given buffer.
 */
void Kernel::convert (char *buffer, int base, int n) {
	char *p = buffer;
	char *p1, *p2;
	uint_t ud = n;
	int div = 10;

	// decimal conversion
	if (base == 'd' && n < 0) {
		*p++ = '-';
		ud = -ud;
    } else if (base == 'x') {
        div = 16;
	}

	/* divide ud by DIVISOR until ud == 0. */
	do {
		int remainder = ud % div;
		*p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
	} while (ud /= div);

	/* Terminate BUF. */
	*p = 0;

	/* Reverse BUF. */
	p1 = buffer;
	p2 = p - 1;
	while (p1 < p2) {
		char tmp = *p1;
		*p1 = *p2;
		*p2 = tmp;
		p1++;
		p2--;
       }
}
